/**
 * @file  MiraAffineTrans2D.h
 * @author Josep Sabater (jsabaterm@el.ub.edu)
 * @date   September, 2015
 * @version 1.0.0
 * @ingroup MiraGeometryLib
 * @brief  Interface for 2D Affine Transformations.
 *
 * Contains Affine transformation operations.
 */
#ifndef MIRA_AFFINE_TRANS_2D_H
#define MIRA_AFFINE_TRANS_2D_H

#include "MiraPoint2DHom.h"

/**
 * @class AffineTrans2D.h
 * @brief Affine Transformations in 2D
 *
 */
namespace MiraGeometryLib{
    class AffineTrans2D{

    public:
        /**
         * @brief Default constructor for class AffineTrans2D.
         * @details Constructs an Identity Homogeneous 3x3 matrix.
         *
         **/
        AffineTrans2D() : m00_(1), m01_(0), m02_(0), m10_(0), m11_(1), m12_(0), m22_(1){};
        /**
         * @brief Constructor for class AffineTrans2D.
         * @details Constructs an Homogeneous 3x3 matrix for affine transformations.
         * Matrix that transforms a from a given frame to a new one.
         * All values are expressed according to the NEW frame.
         * @param dX A real value expressing translation along X axis.
         * @param dY A real value expressing translation along Y axis.
         * @param r A real value (radians) expressing rotation according Z axis to go from
         * the new frame to the previous one.
         * @param hw A real value expressing the scaling factor.
         *
         **/
        AffineTrans2D(const double& dX,
                      const double& dY,
                      const double& r,
                      const double& hw);
        /**
         * @brief Constructor for class AffineTrans2D.
         * @details Constructs an Homogeneous 3x3 matrix for affine transformations.
         * @param m00 A real value of component m00 of a 2D Homogeneous matrix.
         * @param m01 A real value of component m01 of a 2D Homogeneous matrix.
         * @param m02 A real value of component m02 of a 2D Homogeneous matrix.
         * @param m10 A real value of component m10 of a 2D Homogeneous matrix.
         * @param m11 A real value of component m11 of a 2D Homogeneous matrix.
         * @param m12 A real value of component m12 of a 2D Homogeneous matrix.
         **/
        AffineTrans2D(const double& m00,
                      const double& m01,
                      const double& m02,
                      const double& m10,
                      const double& m11,
                      const double& m12,
                      const double& m22);
        /**
         * @brief Invert an Homogeneous 2D matrix.
         * @return an AffineTrans2D matrix.
         **/
        AffineTrans2D invert() const;

        /**
         * @brief Flip (180 deg) an Homogeneous 2D matrix along Y axis
         * @return an AffineTrans2D matrix.
         **/
        AffineTrans2D flip() const;

        /**
         * @brief Transforms a point.
         * @details Given one point expressed in a given coordinates frame
         * translate it into the frame defined by this object.
         * @return an AffineTrans2D matrix.
         **/
        Point2DHom transform(const Point2DHom& ph) const;

        AffineTrans2D operator * (const AffineTrans2D& righAff) const;
        AffineTrans2D& operator *= (const AffineTrans2D& rightAff);
        friend std::ostream& operator << (std::ostream& os, const AffineTrans2D& aff);

    private:
        double m00_, m01_, m02_; //! < Components of the first row of the Homogeneous mat.
        double m10_, m11_, m12_; //! < Components of the second row of the Homogeneous mat.
        double m22_; //! < Components of the third row of the Homogeneous mat (scale).
    };
}


#endif
